if (!jsx3.lang.Class.forName("ux.cdb.admin.queries.QueryUtil")) {
jsx3.lang.Class.defineClass("ux.cdb.admin.queries.QueryUtil", null, null, 
    function(cache) {

        cache.serverCache = null;
        cache.cacheUtil = {};

        cache._instance = null;
        
        cache.getInstance = function(){
            if(!this._instance) {
                this._instance = new cache(); 
            }
            return this._instance;
        };
        
        cache.prototype.options = [];
        cache.prototype.cacheIdCount = 0;
        cache.prototype.cacheIdStep = 0;
        cache.prototype.callbackScope = this;
        cache.prototype.callbackFunction = function(){};
        
		/**
		* Load data from server. 
		* @params options(Array) [{dwrClass,dwrFunction,dwrParams}...] options which you want to load.
		*/
        cache.loadCustomizeCache = function(options, scope, callback) {
            if(!options || !(options instanceof Array)) {
                throw new jsx3.lang.IllegalArgumentException('options must be a array and content with "[{dwrClass:<dwrClassName>,dwrFunction:<dwrFunctionName>,dwrParams:<dwrParams>}]"!', 'cacheType : "' + cacheType + '"');
                return;
            }
			if(!cache.serverCache){
				cache.serverCache = ux.megatron.Main.getServer().getCache();
			}
            try{
                var _cache = cache.getInstance();
				_cache.options = options;
                _cache.cacheIdCount = options.length;
                _cache.callbackScope = scope || this;
                if(callback && typeof(callback) == 'function') { 
                    _cache.callbackFunction = callback;
                }
                ux.megatron.util.Dwr.beginBatch();
                for(var i=0;i<_cache.cacheIdCount;i++){
                    var option = options[i];
					var cacheType = _cache.getCacheType(option);
                    var childObj = cache.cacheUtil[cacheType];
/* @JSC :: begin DEBUG */
                    jsx3.log('CacheUtil#loadCache cacheType[' + cacheType + '], cacheObj:' + childObj);
/* @JSC :: end */
                    if(childObj && childObj.obj && childObj.obj.toString() != '<data jsxid="jsxroot"/>') {
/* @JSC :: begin DEBUG */
                        jsx3.log('CacheUtil#loadCache cacheObj.obj : ' + dwr.util.toDescriptiveString(childObj.obj, 2));
/* @JSC :: end */
                        _cache._setCallback();
                    }else{
/* @JSC :: begin DEBUG */
                        jsx3.log('CacheUtil#loadCache load cacheObj.obj ...');
/* @JSC :: end */
                        cache.cacheUtil[cacheType] = {name:"CustomizeCache_" + cacheType, obj:null};
/* @JSC :: begin DEBUG */
                        jsx3.log('CacheUtil#loadCache _loadData("' + dwr.util.toDescriptiveString(option, 2) + '", "' + cacheType + '");');
/* @JSC :: end */
                        _cache._loadData(option, cacheType);
                    }
                }
                ux.megatron.util.Dwr.endBatch();
            }catch(e){
                jsx3.log('CacheUtil#loadCache Error : ' + e.message);
                throw e;
            }
        };
        
        cache.prototype.getCache = function(index) {
			var cacheType = this.getCacheType(this.options[index]);
            if(!cacheType || typeof(cacheType) != 'string') {
                throw new jsx3.lang.IllegalArgumentException('parameters must be a number!', 'options['+index+']: "' + dwr.util.toDescriptiveString(this.options[index], 2) + '", cacheType:' + cacheType);
            }
			var obj = cache.cacheUtil[cacheType].obj;
            return obj;
		};
		
		/**
		* get object of common cache.
		* @params index(int)  index of options. 
		* @params filter(object) filter of response data.
		*/
        cache.prototype.getCacheAsCDF = function(index, fiter) {
            var _cache = this.getCache(index);
			var cdf = jsx3.xml.CDF.Document.newDocument();
			if(_cache && _cache instanceof Array){
				cdf.insertRecord(cache.getDefaultOption());
				if(fiter && fiter instanceof Object){
					for(var i=0,item;item = _cache[i];i++){
						var tmpObj = {};
						for(var o in fiter)
							tmpObj[o] = item[fiter[o]];
						cdf.insertRecord(tmpObj);
					}
				}else{
					for(var i=0,item;item = _cache[i];i++){
						cdf.insertRecord(item);
					}
				}
				_cache = cdf;
			}
/* @JSC :: begin DEBUG */
            jsx3.log('CacheUtil#getCache: ' + cdf);
/* @JSC :: end */
            return cdf.cloneDocument();
        };
		
        cache.prototype.getCacheType = function(option) {
			try{
/* @JSC :: begin DEBUG */
				jsx3.log('CacheUtil#getCacheType option:' + dwr.util.toDescriptiveString(option, 4));
/* @JSC :: end */
				return 	option.dwrClass + '_' + 
						option.dwrFunction + '_' + 
						option.dwrParams.length + '_' +
						option.dwrParams.join('_');
			}catch(e){
                throw new jsx3.lang.IllegalArgumentException('parameters may be error!', 'option: "' + dwr.util.toDescriptiveString(option, 2) + '"');
				return null;
			}
		};

        cache.prototype._loadData = function(option, cacheType) {
            if(ux.megatron.Main.isFileSystem()) { return; }
            var dwrClass = option.dwrClass;
            var dwrFunction = option.dwrFunction;
			var dwrParams = option.dwrParams;
            ux.megatron.util.Dwr.callDwr(dwrClass, dwrFunction, [dwrParams.join()], this,
                function(data){
                    if (data !== null && typeof data == 'object') {
						if(!data || !cacheType) {
							throw new jsx3.lang.IllegalArgumentException('parameters required!', 'cacheType : ' + cacheType + ',data : ' + data);
						}
						cache.cacheUtil[cacheType].obj = data.content.data;
/* @JSC :: begin DEBUG */
						if(window.dwr && dwr.util) { jsx3.log(dwr.util.toDescriptiveString(cache.cacheUtil[cacheType].obj, 2)); }
/* @JSC :: end */
						cache.serverCache.clearById(cache.cacheUtil[cacheType].name);
						cache.serverCache.setDocument(cache.cacheUtil[cacheType].name, cache.cacheUtil[cacheType].obj);

						this._setCallback();
                    }
                });
        };
        
        cache.prototype._setCallback = function() {
            this.cacheIdStep++;
/* @JSC :: begin DEBUG */
            jsx3.log('cacheIdStep : ' + this.cacheIdStep + ' | cacheIdCount : ' + this.cacheIdCount);
            jsx3.log('step over : ' + (this.cacheIdStep === this.cacheIdCount));
/* @JSC :: end */
           if(this.cacheIdStep === this.cacheIdCount){
                this.cacheIdStep = 0;
                this.callbackFunction.call(this.callbackScope);
/* @JSC :: begin DEBUG */
				jsx3.log('do callback function : ' + this.callbackFunction);
/* @JSC :: end */
            }
        };
		
		// default option for select box.
		cache.getDefaultOption = function(){
			var _selectProperty = ux.megatron.Main.getServer().getDynamicProperty("@cdb@Select Default Text");
			return {jsxid:'', jsxtext:_selectProperty, jsxstyle:'width:100%;'};
		}

/* @JSC :: begin DEBUG */
        jsx3.log('QueryUtil loading...');
/* @JSC :: end */
    }
);
}